diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-07-28 15:07:57 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-07-28 15:07:57 +0200 |
| commit | 04fabf115ccea31ac504b06cc51d78423b697f60 (patch) | |
| tree | 26c21f8822ccd24fce3a80b7361382c8a87d0c96 /src/routes/grocery/[id]/+page.server.ts | |
| parent | 45cc0afb734a422ee7765dc5c60dccbcc6721367 (diff) | |
refactor: services layer, valibot validation, shared CSS utilities, aria labels, and drizzle migrate
- Extract groceries/categories/references services with db injection
- Add valibot for form validation and safe numeric id parsing
- Fix category delete FK behavior with onDelete: set null + migration
- Replace custom migrate.js with drizzle-orm/libsql/migrator
- Add shared CSS utility classes in app.css (forms, lists, buttons)
- Add aria-pressed and aria-label on interactive elements
- Remove redundant app.css imports and unused /stores import
- Add integration tests for all services using drizzle migrate helper
- Remove smoke test; add db:migrate and db:studio scripts
Diffstat (limited to 'src/routes/grocery/[id]/+page.server.ts')
| -rw-r--r-- | src/routes/grocery/[id]/+page.server.ts | 58 |
1 files changed, 34 insertions, 24 deletions
diff --git a/src/routes/grocery/[id]/+page.server.ts b/src/routes/grocery/[id]/+page.server.ts index b19825a..3c3967a 100644 --- a/src/routes/grocery/[id]/+page.server.ts +++ b/src/routes/grocery/[id]/+page.server.ts @@ -1,11 +1,28 @@ import { error, fail, redirect } from '@sveltejs/kit'; import { db } from '$lib/server/db'; -import { groceries, categories, references } from '$lib/server/db/schema'; +import { groceries, categories } from '$lib/server/db/schema'; import { eq } from 'drizzle-orm'; +import { + loadForGrocery, + add as addRef, + deleteReference, +} from '$lib/server/services/references'; +import { deleteGrocery } from '$lib/server/services/groceries'; +import { + numericId, + parseFormString, + parseOptionalNumber, +} from '$lib/server/services/validation'; +import type { Grocery, Reference } from '$lib/server/services/types'; import type { Actions, PageServerLoad } from './$types'; +export interface GroceryDetailOutput { + item: Grocery & { categoryName: string | null }; + references: Reference[]; +} + export const load: PageServerLoad = async ({ params }) => { - const id = Number(params.id); + const id = numericId(params.id); const [item] = await db.select().from(groceries).where(eq(groceries.id, id)); if (!item) throw error(404, 'Article introuvable'); @@ -17,10 +34,7 @@ export const load: PageServerLoad = async ({ params }) => { .where(eq(categories.id, item.categoryId)) : [null]; - const refs = await db - .select() - .from(references) - .where(eq(references.groceryId, id)); + const refs = await loadForGrocery(id); return { item: { @@ -34,38 +48,34 @@ export const load: PageServerLoad = async ({ params }) => { export const actions: Actions = { add: async ({ request, params }) => { const data = await request.formData(); - const reference = data.get('reference')?.toString().trim(); - const price = data.get('price')?.toString().trim(); - const unit = data.get('unit')?.toString().trim(); - const qualityScore = data.get('quality_score')?.toString().trim(); + const groceryId = numericId(params.id); + const reference = parseFormString(data.get('reference')); + const price = parseOptionalNumber(data.get('price')); + const unit = parseFormString(data.get('unit')); + const qualityScore = parseOptionalNumber(data.get('quality_score')); if (!reference) { return fail(400, { error: 'La référence est requise' }); } - await db.insert(references).values({ - groceryId: Number(params.id), - reference, - price: price ? Number(price) : null, - unit: unit || null, - qualityScore: qualityScore ? Number(qualityScore) : null, - }); - + await addRef(groceryId, reference, price, unit, qualityScore); return { success: true }; }, delete: async ({ request }) => { const data = await request.formData(); - const id = Number(data.get('id')); - - await db.delete(references).where(eq(references.id, id)); - + try { + const id = numericId(data.get('id')); + await deleteReference(id); + } catch { + return fail(400, { error: 'ID invalide' }); + } return { success: true }; }, deleteItem: async ({ params }) => { - await db.delete(groceries).where(eq(groceries.id, Number(params.id))); - + const groceryId = numericId(params.id); + await deleteGrocery(groceryId); throw redirect(303, '/'); }, }; |
